package dk.itu.spvc.bluefriends;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;

import dk.itu.spvc.bluefriends.classes.Constant;
import dk.itu.spvc.bluefriends.classes.Profile;
import itu.beddernet.approuter.IBeddernetService;
import itu.beddernet.approuter.IBeddernetServiceCallback;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class BlueFriends extends Activity implements ServiceConnection {
	private static final String TAG = BlueFriends.class.getSimpleName();

	public static String applicationIdentifier = "dk.itu.spvc.bluefriends";
	public static long applicationIdentifierHash;

	private ServiceConnection sc = this;
	protected static IBeddernetService beddernetService;
	protected static Profile myProfile = new Profile();
	
	//message identifiers
	protected static final String TWEET = "TWEET";
	protected static final String REQUEST = "REQUEST";
	protected static final String CONFIRMREQUEST = "CONFIRMREQUEST";
	protected static final String MESSAGE = "MESSAGE";
	protected static final String MEMBERINFO = "MEMBERINFO";
	protected static final String RESPONDINFO = "RESPONDINFO";
	
	protected static List<Profile> members=new ArrayList<Profile>();
	DateFormat dateFormat = new SimpleDateFormat("HH:mm dd/MMM");
	Calendar cal = Calendar.getInstance();

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		//add mySelf to the list for testing purpose,should be removed later
		bind(); 
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu){
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.editProfile:
			Intent startIntent = new Intent(this,ProfileActivity.class);
			startIntent.putExtra("isEditing", true);
			startActivity(startIntent);
			return true;
		case R.id.quit:
			finish();
			return true;
		case R.id.setDiscoverable:
			try {
				beddernetService.setDiscoverable(true);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	private void bind() {
		Intent bindIntent = new Intent(IBeddernetService.class.getName());
		boolean b = this.bindService(bindIntent, this, Context.BIND_AUTO_CREATE);
		if(b)Log.d(TAG, "successfully bound to beddernet");
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		if (beddernetService != null) {
			try {
				beddernetService.unregisterCallback(callback,applicationIdentifier);
			} catch (RemoteException e) {
				Log.e(TAG, "Console could't unregister callback", e);
			}
			unbindService(sc);
		}
	}

	@Override
	protected void onResume() {
		if (beddernetService == null) {
			Log.d(TAG, "the service connection is null - rebooting");
			// onCreate(null);
			bind();
		}
		super.onResume();
	}


	@Override
	public void onServiceDisconnected(ComponentName name) {
	}

	@Override
	public void onServiceConnected(ComponentName className, IBinder service) {
		try {
			Log.d(TAG, "Service connected:" + service.getInterfaceDescriptor());
		} catch (RemoteException e) {
			e.printStackTrace();
			Log.d(TAG, "Service connected but something fucked up");
		}
		beddernetService = IBeddernetService.Stub.asInterface(service);
		if (beddernetService == null)
			Log.e(TAG, "MyService is nul!!?!");
		// Synchronously
		try {
			applicationIdentifierHash = beddernetService.registerCallback(callback, applicationIdentifier);
			Log.d(TAG, "AIH received from server on register: "+ applicationIdentifierHash);
		} catch (RemoteException e) {

			Log.e(TAG,"Remote exception from service while registering callback: "+ e.getMessage());
			e.printStackTrace();
		}
	}

	public boolean insertToDB(String Author,String mes){
		Long now = Long.valueOf(System.currentTimeMillis());
		ContentValues cv = new ContentValues();
		cv.put(Constant.AUTHOR, Author);
		cv.put(Constant.MES, mes);
		cv.put(Constant.DATETIME, " at"+dateFormat.format(cal.getTime()));
		cv.put(Constant.TIMESTAMP, now);
		Uri newUri = getContentResolver().insert(Constant.TWEET_CONTENT_URI, cv);
		if(newUri != null)return true;
		else Log.i(TAG, "Can not insert tweet to database");
		return false;
	}
	
	//TODO remove this method...only used to make fake test profiles!
	public boolean insertTestDataToDB(){
		DateFormat dateFormat = new SimpleDateFormat("HH:mm dd/MMM");
		Calendar cal = Calendar.getInstance();
		ContentValues cv;
		Uri newUri = null;

		String[] username = {"user 1","user 2","user 3","user 4","user 5"};
		String[] email = {"1@mail.com","2@mail.com","3@mail.commale","4@mail.com","5@mail.com"};
		String[] gender = {"male","female","male","female","male"};
		String[] image = {"a","b","c","d","e"};
		String[] isPending = {"true","true","true","false","false"};
		String[] mac = {"11:11:11:11_11","22:22:22:22:22", "33:33:33:33:33","44:44:44:44:44","55:55:55:55:55"};
		String[] phone = {"1111111","2222222","333333","4444444","5555555"};
		String time = " at"+dateFormat.format(cal.getTime());

		for(int i = 0; i<5; i++){
			cv = new ContentValues();
			cv.put(Constant.USERNAME, username[i]);
			cv.put(Constant.EMAIL, email[i]);
			cv.put(Constant.GENDER, gender[i]);
			cv.put(Constant.IMAGE, image[i]);
			cv.put(Constant.ISPENDING, isPending[i]);
			cv.put(Constant.MACADDR, mac[i]);
			cv.put(Constant.PHONENB, phone[i]);
			cv.put(Constant.TIMESTAMP, time);
			newUri = getContentResolver().insert(Constant.PROFILE_CONTENT_URI, cv);
		}
		if(newUri!= null)
			return true;
		else Log.i(TAG, "Can not insert tweet to database");
		return false;
	}

	public IBeddernetServiceCallback callback = new IBeddernetServiceCallback.Stub(){
		@Override
		public long getApplicationIdentifierHash() throws RemoteException {
			return applicationIdentifierHash;
		}

		@Override
		public void update(String senderAddress, byte[] message)throws RemoteException {
			String[] mes = new String(message).split("\\|");
			String type = mes[0];
			if(type.equals(TWEET)){
				insertToDB(mes[1], mes[2]);
			}
			else if(type.equals(REQUEST)){
				//ToDo:implementation of a request
				Long now = Long.valueOf(System.currentTimeMillis());
				ContentValues cv = new ContentValues();
				cv.put(Constant.USERNAME, mes[1]);
				cv.put(Constant.EMAIL, mes[2]);
				cv.put(Constant.GENDER, mes[3]);
				cv.put(Constant.MACADDR, mes[4]);
				cv.put(Constant.PHONENB, mes[5]);
				cv.put(Constant.TIMESTAMP,now);
				cv.put(Constant.ISPENDING, "true");
				Uri newUri = getContentResolver().insert(Constant.PROFILE_CONTENT_URI, cv);
				if(newUri == null)Log.i(TAG, "Can not insert a request to database");
			}
			else if(type.equals(CONFIRMREQUEST)){
				
			}
			else if(type.equals(MESSAGE)){
				//ToDo:implementation of a private message
			}
			else if(type.equals(MEMBERINFO)){
				String myInfo=RESPONDINFO+"|"+myProfile.getUserName()+"|"+myProfile.getGender();
				beddernetService.sendUnicast(senderAddress, null, myInfo.getBytes(), applicationIdentifier);
			}
			else if(type.equals(RESPONDINFO)){
				Profile peer=new Profile(mes[1],mes[2],senderAddress);
				members.add(peer);
			}
		}

		@Override
		public void updateWithSendersApplicationIdentifierHash(
				String senderAddress, long senderApplicationIdentifierHash,
				byte[] message) throws RemoteException {
			update(senderAddress, message);
		}
	};

}